﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Yuchen.SOA.Utils;
namespace Xinchen.SOA.GateWay
{
    /// <summary>
    /// 处理应用访问授权
    /// </summary>
    public class AuthHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            ApplicationContext appContext = new ApplicationContext();
            ApplicationContext.Current = appContext;
            var url = request.RequestUri.LocalPath.TrimStart('/');
            var routeInfo = url.Split('/');
            if (routeInfo.Length < 2)
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, "地址格式错误:" + request.RequestUri.ToString() + ",格式为：{service}/{action}"));
            }
            var service = routeInfo[0];
            var action = routeInfo[1];
            var applicationIdString = request.Headers.GetValue("applicationId");
            if (string.IsNullOrWhiteSpace(applicationIdString))
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, "http头中未找到applicationId"));
            }
            var applicationId = 0;
            if (!int.TryParse(applicationIdString, out applicationId) || applicationId <= 0)
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, "http头中找到的applicationId有误"));
            }
            var applicationKey = request.Headers.GetValue("applicationKey");
            if (string.IsNullOrWhiteSpace(applicationKey))
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, "http头中未找到applicationKey"));
            }
            appContext.ApplicationId = applicationIdString;
            var appMgr = ApplicationManager.GetInstance();
            var app = appMgr.GetApplication(applicationId);
            if (app == null)
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("applicationId为{0}的应用不存在", applicationId)));
            }
            if (!appMgr.VerifyApplication(applicationId, applicationKey))
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("applicationId为{0}的应用认证失败", applicationId)));
            }
            var serviceClient = ServiceClient.GetInstance();
            var pr = appMgr.GetApplicationServices(applicationId);
            var applicationService = pr.FirstOrDefault(x => x.ContractName.EndsWith(service, StringComparison.OrdinalIgnoreCase));
            if (applicationService == null)
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("该应用无权限访问，applicationId为{0}的应用可访问服务列表中没有服务{1}",
                    applicationId, service)));
            }
            var applicationServiceActions = appMgr.GetApplicationServiceActions(applicationService.Id);
            if (!applicationServiceActions.Any(x => x.ServiceActionName == action))
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("该应用无权限访问，" +
                "applicationId为{0}的应用的服务{1}的可访问Action列表中没有找到Action {2} ",
                    applicationId, service, action)));
            }
            var serviceInfo = serviceClient.GetService(applicationService.ServiceId);
            if (serviceInfo == null)
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("ServiceId为{0}的服务不存在",
                    applicationService.ServiceId)));
            }
            appContext.ServiceName = serviceInfo.ServiceName;
            var serviceHostingInfo = ServiceHostingClient.GetInstance().GetServiceHosting(applicationService.ServiceHostingId);
            if (serviceHostingInfo == null)
            {
                throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound, string.Format("ServiceHostingId为{0}的服务宿主不存在",
                    applicationService.ServiceHostingId)));
            }
            appContext.ServiceHostingAddress = serviceHostingInfo.Address;
            appContext.Action = action;
            return base.SendAsync(request, cancellationToken);
        }
    }
}
